package com.cmii.sjw.department.control.jsc.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.cmii.sjw.department.control.jsc.model.LoginBody;
import com.cmii.sjw.department.control.jsc.model.User;
import com.cmii.sjw.department.control.jsc.model.dto.UserQueryDTO;
import com.cmii.sjw.department.control.jsc.model.entity.Menu;
import com.cmii.sjw.department.control.jsc.model.entity.Role;
import com.cmii.sjw.department.control.jsc.model.vo.MenuNode;
import com.cmii.sjw.department.control.jsc.model.vo.UserVo;
import com.cmii.sjw.department.control.jsc.service.IUserService;
import com.cmii.sjw.department.control.jsc.service.UserRoleService;
import com.cmii.sjw.department.control.jsc.service.impl.LoginService;
import com.cmii.sjw.department.control.jsc.util.MenuTreeUtil;
import com.cmii.sjw.department.control.jsc.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 登录
 * @Author jfh
 * @Date 2024-11-12 周二 16:57
 * @Version 1.0
 */
@Slf4j
@RestController
@CrossOrigin
@RequestMapping("/acc")
public class LoginController {

    @Autowired
    private LoginService loginService;

    @Autowired
    private IUserService userService;

    @Autowired
    private UserRoleService userRoleService;

    /**
     *
     *
     * 登录
     * @param loginBody
     * @return
     */
    @PostMapping("/doLogin")
    public Result doLogin(LoginBody loginBody, HttpServletRequest request) {
        log.info("LoginBody: {}", loginBody);

        String clientIp = getClientIpAddress(request);
        log.info("Client IP: {}", clientIp);
        Result result;
        if ("0".equals(loginBody.getType())) {
            result = loginService.unverifiedLogin(loginBody.getUsername(),clientIp);
        }else{
            result = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid(),clientIp);
        }

        // 记录登录成功的访问日志
        if (result.getCode() == 200) {
            long userId = StpUtil.getLoginIdAsLong();
            loginService.recordAccessLog(userId, clientIp, "登录成功");
        }

        return result;
    }

    /**
     * 获取用户信息
     * @return Result
     */
    @PostMapping("/userInfo")
    public Result getUserInfo() {

        long userId = StpUtil.getLoginIdAsLong();
        // 获取用户基本信息
        User user = userService.getById(userId);
        if (user == null) {
            return Result.error("用户不存在");
        }
        // 复制属性到 UserVo
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);

        // 获取用户的菜单树
        List<Menu> menus = userRoleService.getMenusByUserId(userId);
        List<MenuNode> menuTree = MenuTreeUtil.buildTree(menus);

        // 获取用户角色
        List<Role> roles = userService.getUserRoles(userId);
        List<String> roleNames = roles.stream()
                .map(Role::getRoleName)
                .collect(Collectors.toList());
        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("userInfo", userVo);
        result.put("menu",menuTree);
        result.put("roles", roleNames);

        return Result.success(result);
    }

    /**
     * 获取客户端IP地址
     * @param request
     * @return
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 查询登录状态
     * @return
     */
    @PostMapping("isLogin")
    public Result isLogin() {
        if (StpUtil.isLogin()){
            return Result.success(StpUtil.getTokenInfo());
        }else{
            return Result.error("请登录",false);
        }
    }

    /**
     *  查询 Token 信息
     * @return
     */
    @PostMapping("tokenInfo")
    public Result tokenInfo() {
        return Result.success(null,StpUtil.getTokenInfo());
    }

    /**
     * 注销
     * @return
     */
    @PostMapping("logout")
    public Result logout(HttpServletRequest request) {
        long userId = StpUtil.getLoginIdAsLong();
        String clientIp = getClientIpAddress(request);

        // 记录注销成功的访问日志
        loginService.recordAccessLog(userId, clientIp, "退出成功");

        StpUtil.logout();
        return Result.success();
    }

    /**
     * 用户注册
     * @param username 用户名
     * @param password 密码
     * @return
     */
    @PostMapping("/register")
    public Result register(@RequestParam String username, @RequestParam String password) {
        // 校验密码复杂度
        if (!isPasswordValid(password)) {
            return Result.error("密码复杂度不足，密码必须包含大小写字母、数字和特殊字符，且长度至少为8位，最多为20位");
        }

        // 调用注册服务
        return loginService.register(username, password);
    }

    /**
     * 修改用户密码
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     * @return
     */
    @PostMapping("/changePassword")
    public Result changePassword(@RequestParam String oldPassword, @RequestParam String newPassword) {
        // 校验新密码复杂度
        if (!isPasswordValid(newPassword)) {
            return Result.error("新密码复杂度不足，密码必须包含大小写字母、数字和特殊字符，且长度至少为8位，最多为20位");
        }

        // 获取当前登录用户ID
        long userId = StpUtil.getLoginIdAsLong();
        // 调用修改密码服务
        return loginService.changePassword(userId, oldPassword, newPassword);
    }

    /**
     * 获取用户菜单
     * @param userQueryDTO 用户查询DTO
     * @return 用户菜单列表
     */
    @PostMapping("/userMenus")
    public Result<List<Menu>> getUserMenus(@RequestBody UserQueryDTO userQueryDTO) {
        List<Menu> menus =userService.getUserMenus(userQueryDTO.getUserId());
        return Result.success(menus);
    }

    /**
     * 获取用户角色
     * @param userQueryDTO 用户查询DTO
     * @return 用户角色列表
     */
    @PostMapping("/userRoles")
    public Result<List<Role>> getUserRoles(@RequestBody UserQueryDTO userQueryDTO) {
        List<Role> roles = userService.getUserRoles(userQueryDTO.getUserId());
        return Result.success(roles);
    }

    /**
     * 校验密码复杂度
     * @param password 密码
     * @return 是否满足复杂度要求
     */
    private boolean isPasswordValid(String password) {
        // 密码长度至少为8位
        if (password.length() < 8 || password.length() > 20) {
            return false;
        }

        // 包含至少一个大写字母
        boolean hasUpperCase = !password.equals(password.toLowerCase());
        // 包含至少一个小写字母
        boolean hasLowerCase = !password.equals(password.toUpperCase());
        // 包含至少一个数字
        boolean hasDigit = password.matches(".*\\d.*");
        // 包含至少一个特殊字符
        boolean hasSpecialChar = password.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?].*");

        return hasUpperCase && hasLowerCase && hasDigit && hasSpecialChar;
    }

}
